/*
	负责整个应用生命周期得维护管理
*/
package application

import (
	"fmt"
	"gitee.com/whilew/cream/pkg/basic_component/conf"
	"gitee.com/whilew/cream/pkg/basic_component/log"
	"gitee.com/whilew/cream/pkg/basic_component/orm"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

/*
	定义服务接口
	StartUp 启动服务
	Stop 停止服务
*/
type Service interface {
	StartUp() error
	Stop() error
}

var (
	// 应用初始化函数
	initializeFns = []func() error{
		//flag.Initialize,
		conf.Initialize,
		log.Initialize,
		orm.Initialize,
	}
	initOnce = sync.Once{} // 确保应用只初始化一次
	services = []Service{} // 应用内得服务
	//maxExitWaitTime = 5 * time.Minute // todo 最大退出等待时间
)

func AppendInitialize(i func() error) {
	initializeFns = append(initializeFns, i)
}

/*
	初始化应用
*/
func Initialize() {
	initOnce.Do(func() {
		fmt.Println("开始初始化应用 ...")
		st := time.Now()
		fmt.Println("--------------------------")
		for _, f := range initializeFns {
			if err := f(); err != nil {
				panic(err)
			}
			fmt.Println("--------------------------")
		}
		fmt.Println("初始化成功，耗时： " + fmt.Sprint(time.Now().Sub(st)))
	})
	return
}

func StartUpService(p Service) {
	services = append(services, p)
	go func() {
		if err := p.StartUp(); err != nil {
			panic(err)
		}
	}()
}

func KeepAlive() {
	/*
					监听系统信号
		SIGHUP = 终端控制进程结束(终端连接断开)
		SIGQUIT = 用户发送QUIT字符(Ctrl+/)触发
		SIGTERM = 结束程序(可以被捕获、阻塞或忽略)
		SIGINT = 用户发送INTR字符(Ctrl+C)触发
	*/

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	for {
		select {
		case <-c:
			for _, p := range services {
				if err := p.Stop(); err != nil {
					fmt.Println(err.Error())
				}
			}
			os.Exit(0)
		}
	}
}
